﻿using System;
using System.Collections.Generic;
using Raven.Client.Document;
using Sponsorship.Domain;
using Sponsorship.Domain.Persons;
using Sponsorship.Domain.Sponsors;
using Sponsorship.Domain.Sponsorships;
using Sponsorship.Infrastructure.BootStrapping;
using Sponsorship.ReadModel;
using StructureMap;

namespace Sponsorship.RavenDB.Replayer
{
    internal class Program
    {
        private static IContainer Container;

        private static void Initialize()
        {
            var docStore = new DocumentStore
                               {
                                   ConnectionStringName = BootStrapper.RavenDbConnectionStringName
                               };
            docStore.Initialize();

            Container = BootStrapper.BootStrap (docStore);
        }

        private static void Main (string[] args)
        {
            Initialize();

            ReplayEvents (TemplateEvents (SponsorEvents()));
        }

        private static void ReplayEvents (IEnumerable<IEvent> replayEvents)
        {
            foreach (var evnt in replayEvents)
            {
                Type handlerType = typeof (IEventHandler<>)
                    .MakeGenericType (evnt.GetType());

                foreach (dynamic handler in Container.GetAllInstances (handlerType))
                {
                    handler.Handle ((dynamic) evnt);
                }
            }
        }


        private static IEnumerable<IEvent> SponsorEvents()
        {
            Guid sponsorId = Guid.NewGuid();
            Guid person1Id = Guid.NewGuid();
            Guid person2Id = Guid.NewGuid();
            Guid sponsorshipId1 = Guid.NewGuid();
            Guid sponsorshipId2 = Guid.NewGuid();
            yield return new SponsorEntered (sponsorId, "Rapunzel", "H", new BankInformation ("12345", "6789", "IBAN-12345", "SW-6789"), new Address ("Hauptstraße", "1", "1234", "Wien", "Austria"), "rapunzel.h@invalid.com", "+431123456789", "Comment");
            yield return new SponsorChanged (sponsorId, "R.", "Schneewittchen", null, null, null, null, null);
            yield return new PersonEntered (person1Id, "Hallo", "Welt", DateTime.Now.AddYears (-14), null, SponsoringStatus.Sponsorable, null);
            yield return new PersonEntered (person2Id, "Batman", "Robin", DateTime.Now.AddYears (-7), null, SponsoringStatus.Sponsorable, null);
            yield return new SponsorshipEntered (sponsorshipId1, Guid.NewGuid(), person1Id, sponsorId, 42.42m, DateTime.Now, DateTime.Now.AddMonths (5), new Period(), "Comment");
            yield return new SponsorshipChanged (sponsorshipId1, Guid.NewGuid(), person1Id, sponsorId, 84.84m, DateTime.Now, DateTime.Now.AddMonths (5), new Period(), "Comment");
            yield return new PersonChanged (person1Id, "Hello", "World", DateTime.Now.AddYears (-14), null, SponsoringStatus.Sponsorable, null);
            yield return new SponsorshipEntered (sponsorshipId2, Guid.NewGuid(), person2Id, sponsorId, 21.21m, null, null, Period.Monthly, null);
            yield return new SponsorshipDeleted (sponsorshipId2);
        }

        private static IEnumerable<IEvent> TemplateEvents (IEnumerable<IEvent> events)
        {
            foreach (var evnt in events)
            {
                evnt.SetHeader (Event.EventVersionKey, "1");
                yield return evnt;
            }
        }
    }
}